<?php


namespace App\Models\CacheModel;


use App\Models\Api\BaseCache;
use think\Exception;
use AstroTool\Cache\CacheManage;

class ZlUserStarNumRecord extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.zl_user_star_num_record';

    protected $cacheModel = 'user.user_vip_star_num_record';

    /**
     * 获取成长记录列表信息
     * @param int $uid
     * @param int $type
     * @return array|mixed
     * @throws \Exception
     */
    public function getRecordList(int $uid, int $type)
    {
        $data = $this->getListPage($uid, 'id', [], $type, 'desc', 0);

        $vipTaskConfig = config('vip_task');

        $listData = [];
        foreach ($data['data'] as $key => $value)
        {
            $listData[] = [
                'name' => $vipTaskConfig[$value['type']]['record_name'] ?? '',
                'type' => (int)($value['flag'] ?? 1),
                'star_num' => (int)($value['star_num'] ?? 0),
                'create_time' => date('Y.m.d H:i:s', $value['create_time']),
                'icon' => $vipTaskConfig[$value['type']]['record_icon'] ?? ''
            ];
        }
        $data['data'] = $listData;

        return $data;
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            $where = [];
            if ($ids)
            {
                $where['id'] = ['in', $ids];
            } elseif (($type[1] ?? 0) > 0)
            {
                $where['flag'] = $type[1];
            }
            $where['uid'] = $type[0];

            $data = $this->where($where)->order("id {$sortType}")->column('type,uid,flag,star_num,create_time', 'id');
        }
        catch (Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    /**
     * 未开启缓存从数据库获取分页数据
     * @param array $type 分页数据状态
     * @param string $sortType 排序方式
     * @return array
     */
    public function getPaginateInData($type, $sortType)
    {
        try
        {
            $where = [];
            if (($type[1] ?? 0) > 0)
            {
                $where['flag'] = $type[1];
            }
            $where['uid'] = $type[0];

            $data = $this->where($where)->order("id {$sortType}")
                ->field('type,uid,flag,star_num,create_time')
                ->paginate()
                ->toArray();
        }
        catch (Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    /**
     *  获取用户每月星力值获取总数
     * @param int $uid
     * @return int
     * @throws \Exception
     */
    public function getStarNumMonthlyLimit(int $uid): int
    {
        $cacheConfig = config('cache.user');
        $redisKey = str_replace('[ID]', date('Y-m'), $cacheConfig['star_num_monthly_limit']['list']);
        /**
         * 获取Redis 操作句柄
         */
        $redis = CacheManage::getInstance()->redisHandler;
        $num = 0;
        if ($redis)
        {
            if ($redis->exists($redisKey))
            {   // 缓存存在
                $starNum = $redis->zScore($redisKey, $uid);
                $num = $starNum === false ? 0 : $starNum;
            } else
            {   // 缓存不存在
                $rankingList = $this->getStarNumMonthlyLimitByDb($uid);
                if (!$rankingList)
                {
                    return 0;
                }
                foreach ($rankingList as $id => $starNum)
                {   // 重写缓存
                    $redis->zAdd($redisKey, [], $starNum, $id);
                    if ($uid == $id)
                        $num = $starNum;
                }
            }
        } else
        {
            $rankingList = $this->getStarNumMonthlyLimitByDb($uid);
            $num = $rankingList[$uid] ?? 0;
        }

        return $num;
    }

    /**
     * 获取用户每月星力值总数
     * @param $uid
     * @return array|null
     */
    private function getStarNumMonthlyLimitByDb($uid)
    {
        try
        {
            $time = strtotime(date('Y-m-01 00:00:00'));

            $data = $this->where(['create_time', ['>', $time], 'star_num' => ['>', 0]])->group('uid')->column("SUM(star_num)", 'uid');
            if (empty($data))
            {
                $data[$uid] = 0;
            }
        }
        catch (Exception $e)
        {
            $data = null;
        }

        return $data;
    }

    /**
     * 更新本月获取星力值总数
     * @param int $uid
     * @param int $starNum
     * @throws \Exception
     */
    public function updateMonthStarNum(int $uid, $starNum = 0)
    {
        $cacheConfig = config('cache.user');
        $redisKey = str_replace('[ID]', date('Y-m'), $cacheConfig['star_num_monthly_limit']['list']);
        /**
         * 获取Redis 操作句柄
         */
        $redis = CacheManage::getInstance()->redisHandler;
        if ($redis->exists($redisKey))
        {
            $redis->zAdd($redisKey, [], $starNum, $uid);
        }
    }

    /**
     * 添加成长明细缓存
     * @param $uid
     * @param int $id
     * @param int $flag 1收入 2支出
     * @throws \Exception
     */
    public function addRecordCache($uid, int $id, int $flag = 1)
    {
        $this->listDataAdd($uid, [$id => $id], 0);
        $this->listDataAdd($uid, [$id => $id], $flag);
    }

    /**
     * 用户完成情况
     * @param int $uid
     * @return array|bool|mixed
     * @throws \Exception
     */
    public function getTaskSuccessInfo(int $uid)
    {
        $key = date('Ymd') . ':' . $uid;
        $data = CacheManage::getInstance()->setCacheConfig('user.task_success_today', $key)->getDataAndSet(function () use ($uid)
        {
            return $this->getTodayTaskSuccess($uid);
        });

        return $data;
    }

    /**
     * 任务完成 记录
     * @param int $uid
     * @param int $type
     * @throws \Exception
     */
    public function taskSuccess(int $uid, int $type)
    {
        $key = date('Ymd') . ':' . $uid;
        CacheManage::getInstance()->setCacheConfig('user.task_success_today', $key)->setCache([$type => 1]);
    }

    /**
     * 通过数据库获取今天 任务完成情况  9每日登陆 14会员到期
     * @param int $uid
     * @return array
     */
    private function getTodayTaskSuccess(int $uid): array
    {
        try
        {
            $data = [
                9 => 0,
                14 => 0
            ];
            $list = $this->where('uid', $uid)->whereIn('type', [9, 14])->whereTime('create_time', 'd')->field('type')->select();
            foreach ($list as $value)
            {
                $data[$value['type']] = 1;
            }
        }
        catch (Exception $e)
        {
            return [
                9 => 0,
                14 => 0
            ];
        }

        return $data;
    }

    /**
     * 获取用户成长超越用户百分比 返回 0-100整数
     * @param int $uid
     * @return int
     * @throws \Exception
     */
    public function getUserPercentOver(int $uid): int
    {
        /**
         * 获取Redis 操作句柄
         */
        $redis = CacheManage::getInstance()->redisHandler;
        // 获取用户本月成长星力值
        $monthStarNum = $this->getStarNumMonthlyLimit($uid);

        if ($redis && $monthStarNum > 0)
        {
            $cacheConfig = config('cache.user');
            $key = str_replace('[ID]', date('Y-m'), $cacheConfig['star_num_monthly_limit']['list']);
            $ranking = $redis->zRevRank($key, $uid); // (从大到小)排列的排名 排名以 0 为底
            $ranking++;
            // 获取VIP用户总数
            $vipUserNum = (new ZlUserVip())->vipNum();
            $overNum = $vipUserNum - $ranking; // 超过的人数
            if ($overNum <= 0)
            {
                return 21;
            } else
            {
                if ($vipUserNum === 1)
                {   // 如果只有一个VIP用户
                    return 99;
                } else
                {
                    $res = sprintf('%.2f', $overNum / ($vipUserNum - 1)) * 100;
                }

                if ($res <= 21)
                {
                    $res = 21;
                } elseif ($res > 99)
                {
                    $res = 99;
                }
                return $res;
            }
        } else
        {
            return 21;
        }
    }
}
